package com.luo.gmall.order.service.impl;

import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.luo.gmall.cart.api.entity.Cart;
import com.luo.gmall.order.entity.UserInfo;
import com.luo.gmall.order.exception.OrderException;
import com.luo.gmall.order.feign.*;
import com.luo.gmall.order.interceptor.LoginInterceptor;
import com.luo.gmall.order.service.OrderService;
import com.luo.gmall.order.vo.ConfirmVo;
import com.luo.gmall.order.vo.OrderItem;
import com.luo.gmall.order.vo.OrderSubmitVo;
import com.luo.gmall.pms.entity.SkuAttrValueEntity;
import com.luo.gmall.pms.entity.SkuEntity;
import com.luo.gmall.sms.vo.ItemSaleVo;
import com.luo.gmall.ums.entity.UserAddressEntity;
import com.luo.gmall.ums.entity.UserEntity;
import com.luo.gmall.wms.entity.WareSkuEntity;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author Zoro
 * @date 2021年11月25
 */
@Service
public class OrderServiceImpl implements OrderService {


    @Autowired
    private GmallUmsClient gmallUmsClient;

    @Autowired
    private GmallCartClient gmallCartClient;

    @Autowired
    private GmallPmsClient gmallPmsClient;

    @Autowired
    private GmallWmsClient gmallWmsClient;

    @Autowired
    private GmallSmsClient gmallSmsClient;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private ExecutorService executorService;

    private static final String KEY_PREFIX = "order:token:";

    @Override
    public ConfirmVo confirm() {
        ConfirmVo confirmVo = new ConfirmVo();
        // 获取用户信息
        UserInfo userInfo = LoginInterceptor.getUserInfo();
        Long userId = userInfo.getUserId();


        // 1.根据用户Id查询用户已选中的购物车记录
        CompletableFuture<List<Cart>> cartCompletableFuture = CompletableFuture.supplyAsync(() -> {
            List<Cart> cartList = gmallCartClient.queryCheckCartsByUserId(userId).getData();
            if (CollectionUtils.isEmpty(cartList)) {
                throw new OrderException("你没有购物车记录！");
            }
            return cartList;
        }, executorService);


        CompletableFuture<Void> itemCompletableFuture = cartCompletableFuture.thenAcceptAsync(cartList -> {
            // 只取购物车的skuId和数量（转换成购物车清单集合）
            List<OrderItem> orderItems = cartList.stream().map(cart -> {
                Long skuId = cart.getSkuId();
                OrderItem orderItem = new OrderItem();
                orderItem.setSkuId(skuId);
                orderItem.setCount(cart.getCount());

                // 3.根据skuId查询sku
                CompletableFuture<Void> skuCompletableFuture = CompletableFuture.runAsync(() -> {
                    SkuEntity skuEntity = gmallPmsClient.querySkuById(skuId).getData();
                    if (skuEntity != null) {
                        orderItem.setDefaultImage(skuEntity.getDefaultImage());
                        orderItem.setPrice(skuEntity.getPrice());
                        orderItem.setTitle(skuEntity.getTitle());
                        orderItem.setWeight(BigDecimal.valueOf(skuEntity.getWeight()));
                    }
                }, executorService);

                // 4.根据skuId查询库存信息
                CompletableFuture<Void> stockCompletableFuture = CompletableFuture.runAsync(() -> {
                    List<WareSkuEntity> wareSkuEntities = gmallWmsClient.queryWareSkuBySkuId(skuId).getData();
                    if (!CollectionUtils.isEmpty(wareSkuEntities)) {
                        orderItem.setStore(wareSkuEntities.stream().anyMatch(wareSkuEntity -> wareSkuEntity.getStock() - wareSkuEntity.getStockLocked() > 0));
                    }
                }, executorService);


                // 5.根据skuId查询营销信息
                CompletableFuture<Void> salesCompletableFuture = CompletableFuture.runAsync(() -> {
                    List<ItemSaleVo> itemSaleVos = gmallSmsClient.queryListSalesBySkuId(skuId).getData();
                    orderItem.setSales(itemSaleVos);
                }, executorService);


                // 6.根据skuId查询销售属性
                CompletableFuture<Void> attrsCompletableFuture = CompletableFuture.runAsync(() -> {
                    List<SkuAttrValueEntity> attrValueEntities = gmallPmsClient.queryCurrentSaleAttrValuesBySkuId(skuId).getData();
                    orderItem.setSaleAttrs(attrValueEntities);
                }, executorService);
                CompletableFuture.allOf(skuCompletableFuture, stockCompletableFuture, salesCompletableFuture, attrsCompletableFuture).join();
                return orderItem;
            }).collect(Collectors.toList());
            confirmVo.setItems(orderItems);
        }, executorService);


        // 7.根据用户id查询用户
        CompletableFuture<Void> userCompletableFuture = CompletableFuture.runAsync(() -> {
            UserEntity userEntity = gmallUmsClient.queryUserByUserId(userId).getData();
            if (userEntity != null) {
                confirmVo.setBounds(userEntity.getIntegration());
            }
        }, executorService);


        // 2.根据用户id查询用户的收获地址列表
        CompletableFuture<Void> addressCompletableFuture = CompletableFuture.runAsync(() -> {
            List<UserAddressEntity> userAddressEntities = gmallUmsClient.queryAddressesByUserId(userId).getData();
            confirmVo.setAddresses(userAddressEntities);
        }, executorService);


        // 生成防重token
        CompletableFuture<Void> orderTokenCompletableFuture = CompletableFuture.runAsync(() -> {
            String orderToken = IdWorker.getIdStr();
            confirmVo.setOrderToken(orderToken);
            // 保存到redis
            this.redisTemplate.opsForValue().set(KEY_PREFIX + orderToken, orderToken, 30, TimeUnit.MINUTES);
        }, executorService);

        CompletableFuture.allOf(itemCompletableFuture, userCompletableFuture, addressCompletableFuture, orderTokenCompletableFuture).join();

        return confirmVo;
    }

    @Override
    public void submit(OrderSubmitVo orderSubmitVo) {
        // 1.防重 为了不重复下单

        // 2.验总价 根据skuId分别查出对应的单价，然后进行比价

        // 3.验库存并锁库存 wms-service

        // 4.创建订单 远程oms-service

        // 5.异步删除购物车中对应的记录（性能高 不会导致事务回滚）（删除已经购买商品对应的购物车信息）

    }
}
